<?php

namespace App\Http\Controllers\Api;

use App\Http\Models\Member;
use App\Http\Models\SmsLog;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator as FacadesValidator;

/**
 * 用户权限
 *
 * @Author hechengwei
 * @email chichiooo@sina.com
 * @DateTime 2022-03-08
 */
class AuthController extends BaseController
{
    /**
     * 注册用户
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-12-19
     * @param Request $request
     * @return json
     */
    public function register(Request $request)
    {
        $rules = [
            'username' => ['required', 'mobile'],
            'code' => ['required'],
            'userTypeId' => ['required'],
            'password' => ['required'],
            'confirm_pwd' => ['required', 'same:password'],
        ];

        $message = [
            'username.required' => '手机号不能为空',
            'username.mobile' => '手机号码格式有误',
            'code.required' => '验证码不能为空',
            'userTypeId' => '身份不能为空',
            'password.required' => '密码不能为空',
            'confirm_pwd.required' => '确认密码不能为空',
            'confirm_pwd.same' => '确认密码与密码不一致',
        ];

        $payload = $request->only('username', 'code', 'userTypeId', 'password', 'confirm_pwd');


        $validator = FacadesValidator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        // 验证手机号码是否注册过
        if (Member::checkPhone($payload['username'])) {
            return fail_message('该手机号已注册');
        }

        // 验证验证码
        $verify_code = SmsLog::check_code($payload['code'], $payload['username']);

        if (empty($verify_code)) {
            return fail_message('验证码不正确');
        }

        // 创建用户
        $result = Member::create([
            'username' => $payload['username'],
            'password' => bcrypt($payload['confirm_pwd']),
            'avatar' => env('DEFAULT_AVATAR'),
            'phone' => $payload['username'],
            'reg_ip' => request()->ip(),
            'add_time' => time(),
            'userTypeId' => $payload['userTypeId'],
            'status' => 1,
        ]);

        if ($result) {
            SmsLog::use_code($payload['code'], $payload['username']);
            // return success_message('创建用户成功');
            $token = Auth::guard('api')->login($result);

            if ($token) {
                // 登录成功
                $member = $this->guard()->user();
                $member->last_login_time = time();
                $member->reg_ip = $request->ip();
                $member->save();
                // $wechat = $member->wx;
                return $this->respondWithToken($token);
            }
        } else {
            return fail_message('创建用户失败');
        }
    }

    /**
     * Get a JWT token via given credentials.
     *
     * @param  \Illuminate\Http\Request  $request
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        $rules = [
            'username' => ['required', 'mobile'],
            'password' => ['required'],
            // 'code' => ['required'],
        ];

        $message = [
            'username.required' => '手机号不能为空',
            'username.mobile' => '手机号码格式有误',
            'password.required' => '密码不能为空',
            // 'code.required' => '验证码不能为空',
        ];

        $payload = $request->only('username', 'password'); //, 'code'


        $validator = FacadesValidator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        // 验证手机号码是否注册过
        if (!Member::checkPhone($payload['username'])) {
            return fail_message('手机号未注册');
        }

        $token = Auth::guard('api')->attempt($payload);


        if ($token) {
            // 登录成功
            $member = $this->guard()->user();
            $member->last_login_time = time();
            $member->reg_ip = $request->ip();
            $member->save();
            // $wechat = $member->wx;
            return $this->respondWithToken($token);
        }

        return fail_message('未找到该用户,或密码错误');
    }

    /**
     * Get the authenticated User
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        return success(member());
    }

    /**
     * Log the user out (Invalidate the token)
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        $this->guard()->logout();

        return success_message('退出成功');
    }

    /**
     * Refresh a token.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        try {
            $authToken = Auth::guard('api')->getToken();

            if (!$authToken) {
                return fail([], '未登录', 401);
            }

            $userid = Auth::guard('api')->payload()->get('sub');

            $member = Member::where('userid', $userid)->where('status', 1)->where('is_del', 0)->first();

            if (empty($member)) {
                return fail(
                    [],
                    '未找到该用户',
                    407
                );
            }

            return $this->respondWithToken($this->guard()->refresh());
        } catch (Exception $e) {
            noticeLog('== refresh token error ==' . json_encode($e->getMessage()));
            return fail([], '未登录', 405);
        }
    }

    /**
     * Get the token array structure.
     *
     * @param  string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        return success([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => $this->guard()->factory()->getTTL() * 60, // * 60
        ]);
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return \Illuminate\Contracts\Auth\Guard
     */
    public function guard()
    {
        return Auth::guard($this->guard);
    }


    /**
     * 忘记密码
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-04
     * @param Request $request
     * @return json
     */
    public function forgetPassword(Request $request)
    {
        $rules = [
            'username' => ['required', 'mobile'],
            'code' => ['required'],
            'password' => ['required', 'min:6', 'max:16'],
            'confirm_pwd' => ['required', 'min:6', 'max:16', 'same:password'],
        ];

        $message = [
            'username.required' => '手机号不能为空',
            'username.mobile' => '手机号码格式有误',
            'password.required' => '密码不能为空',
            'password.min' => '密码不能小于 6 位',
            'password.max' => '密码不能大于 16 位',
            'confirm_pwd.required' => '确认密码不能为空',
            'confirm_pwd.min' => '确认密码不能小于 6 位',
            'confirm_pwd.max' => '确认密码不能大于 16 位',
            'confirm_pwd.same' => '确认密码与密码不一致',
            'code.required' => '验证码不能为空',
        ];

        $payload = $request->only('username', 'code', 'password', 'confirm_pwd');

        $validator = FacadesValidator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        // 验证手机号码是否注册过
        if (!Member::checkPhone($payload['username'])) {
            return fail_message('手机号未注册');
        }

        // 验证验证码
        $verify_code = SmsLog::check_code($payload['code'], $payload['username']);

        if (empty($verify_code)) {
            return fail_message('验证码不正确');
        }

        if (md5($payload['password']) !== md5($payload['confirm_pwd'])) {
            return fail_message('密码不一致');
        }

        $member = Member::where(['username' => $payload['username']])->first();

        $member->password = bcrypt($payload['confirm_pwd']);
        if ($member->save()) {
            SmsLog::use_code($payload['code'], $payload['username']);
            return success();
        } else {
            return fail_message();
        }
    }
}
